// Copyright (C) 2012 Tanmay Sinha
// All rights reserved

package org.saakshar;

import static org.saakshar.utils.FontUtils.*;
import static org.saakshar.utils.StringUtils.*;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
import java.util.Set;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 
 * Activity for sight words
 * 
 * @author tanmaysinha
 * 
 */
public class WordsActivity extends Activity implements OnInitListener {

	/** The Tag */
	private static final String TAG = WordsActivity.class.getSimpleName();

	static final List<String> SIGHT_WORDS = Arrays.asList("a", "about",
			"after", "again", "all", "always", "am", "an", "and", "any", "are",
			"around", "as", "ask", "at", "ate", "away", "be", "because",
			"been", "before", "best", "better", "big", "black", "blue", "both",
			"bring", "brown", "but", "buy", "by", "call", "came", "can",
			"carry", "clean", "cold", "come", "could", "cut", "did", "do",
			"does", "done", "don't", "down", "draw", "drink", "eat", "eight",
			"every", "fall", "far", "fast", "find", "first", "five", "fly",
			"for", "found", "four", "from", "full", "funny", "gave", "get",
			"give", "go", "goes", "going", "good", "got", "green", "grow",
			"had", "has", "have", "he", "help", "her", "here", "him", "his",
			"hold", "hot", "how", "hurt", "I", "if", "in", "into", "is", "it",
			"its", "jump", "just", "keep", "kind", "know", "laugh", "let",
			"light", "like", "little", "live", "long", "look", "made", "make",
			"many", "may", "me", "much", "must", "my", "myself", "never",
			"new", "no", "not", "now", "of", "off", "old", "on", "once", "one",
			"only", "open", "or", "our", "out", "over", "own", "pick", "play",
			"please", "pretty", "pull", "put", "ran", "read", "red", "ride",
			"right", "round", "run", "said", "saw", "say", "see", "seven",
			"shall", "she", "show", "sing", "sit", "six", "sleep", "small",
			"so", "some", "soon", "start", "stop", "take", "tell", "ten",
			"thank", "that", "the", "their", "them", "then", "there", "these",
			"they", "think", "this", "those", "three", "to", "today",
			"together", "too", "try", "two", "under", "up", "upon", "us", "us",
			"walk", "want", "warm", "was", "wash", "we", "well", "went",
			"were", "what", "when", "where", "which", "white", "who", "why",
			"will", "wish", "with", "work", "would", "write", "yellow", "yes",
			"you", "your");

	private List<String> selectedWords;

	private TextView sightWordsTextView;

	private TextToSpeech tts;
	private Button nextWordButton;
	private Button previousWordButton;

	private float initialX = 0;
	private float initialY = 0;
	private float deltaX = 0;
	private float deltaY = 0;

	private static String SIGHT_WORD_INDEX = "sight_word_index";
	private static String MY_WORD_INDEX = "my_word_index";
	private static String SIGHT_WORD_SELECTED = "sight_word_selected";

	private static boolean shuffled = false;

	private final OnTouchListener sightWordsOnTouchListener = new OnTouchListener() {

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				deltaX = 0;
				deltaY = 0;
				initialX = event.getRawX();
				initialY = event.getRawY();

				return true;
			}

			if (event.getAction() == MotionEvent.ACTION_UP) {

				deltaX = event.getRawX() - initialX;
				deltaY = event.getRawY() - initialY;

				if (Math.abs(deltaX) >= Math.abs(deltaY)) {
					if (deltaX > 150) {
						Log.d(TAG, "Swiped right");
						animateFlashCard(true);
					} else if (deltaX < -150) {
						Log.d(TAG, "Swiped left");
						animateFlashCard(false);
					}
				}

				return true;

			}

			return true;
		}
	};

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		if (!shuffled) {
			Collections.shuffle(SIGHT_WORDS);
			shuffled = true;
			clearSightWordIndex();
		}

		if (tts == null) {
			tts = new TextToSpeech(this, this);
		}

		ActionBar bar = getActionBar();

		bar.setDisplayShowHomeEnabled(true);
		bar.setDisplayHomeAsUpEnabled(true);

		setContentView(R.layout.words_layout);

		sightWordsTextView = (TextView) findViewById(R.id.word_view);
		sightWordsTextView.setOnTouchListener(sightWordsOnTouchListener);

		nextWordButton = (Button) findViewById(R.id.next_word_button);
		nextWordButton
				.setOnClickListener(new android.view.View.OnClickListener() {

					@Override
					public void onClick(View v) {
						animateFlashCard(false);
					}
				});

		previousWordButton = (Button) findViewById(R.id.previous_word_button);
		previousWordButton
				.setOnClickListener(new android.view.View.OnClickListener() {

					@Override
					public void onClick(View v) {
						animateFlashCard(true);
					}
				});

		if (isSightWordSelected()) {
			showSightWords(false);
		} else {
			showMyWords();
		}

		Typeface typeface = loadFont(this,
				getResources().getString(R.string.fs_me));
		if (typeface != null) {
			sightWordsTextView.setTypeface(typeface);
		}

	}

	@Override
	public void onInit(int status) {
		if (status == TextToSpeech.SUCCESS) {
			tts.setLanguage(Locale.US);
		} else {
			Log.e(TAG, "Could not initialize TextToSpeech.");
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.sight_words_activity_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case (R.id.article_sight_word_item):
		case (android.R.id.home):
			Intent intent = new Intent(this, ReaderActivity.class);
			startActivity(intent);
			break;
		case (R.id.sight_word_speak_item):
			String currentSightWord = sightWordsTextView.getText().toString();
			if (!isBlank(currentSightWord)) {
				tts.speak(currentSightWord, TextToSpeech.QUEUE_FLUSH, null);
			}
			break;
		case (R.id.sight_words_item):
			showSightWords(false);
			break;
		case (R.id.my_words_item):
			showMyWords();
			break;
		case (R.id.clear_saved_words):
			AlertDialog clearFileDialog = new AlertDialog.Builder(this)
					.setMessage("Are you sure you want to clear saved words?")
					.setCancelable(false)
					.setPositiveButton("Yes", new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							deleteFile(getString(R.string.my_word_file_name));
							clearMyWordIndex();
							showSightWords(true);
						}
					}).setNegativeButton("No", new OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							dialog.cancel();
						}
					}).create();

			clearFileDialog.show();
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (tts != null) {
			tts.shutdown();
		}
	}

	private void showMyWords() {
		selectedWords = loadMyWords();
		if (!selectedWords.isEmpty()) {
			sightWordsTextView.setBackgroundDrawable(getResources()
					.getDrawable(R.drawable.my_word_card));

			int storedIndex = getMyWordIndex();
			if (storedIndex > selectedWords.size() || storedIndex < 0) {
				clearMyWordIndex();
			}

			sightWordsTextView.setText(selectedWords.get(getMyWordIndex()));
			setSightWordSelected(false);
		} else {
			Toast.makeText(this, "No saved words", Toast.LENGTH_LONG).show();
			getPreferences(MODE_PRIVATE).edit().putInt(MY_WORD_INDEX, 0);
			selectedWords = SIGHT_WORDS;
			showSightWords(false);
		}

	}

	private void showSightWords(boolean cleared) {
		sightWordsTextView.setBackgroundDrawable(getResources().getDrawable(
				R.drawable.word_card));
		selectedWords = SIGHT_WORDS;
		setSightWordSelected(true);
		sightWordsTextView.setText(selectedWords.get(getSightWordIndex()));

		if (cleared) {
			Toast.makeText(this, "Cleared Saved Words", Toast.LENGTH_LONG)
					.show();
		}
	}

	private List<String> loadMyWords() {
		Set<String> myWords = new HashSet<String>();
		try {
			FileInputStream fis = openFileInput(getString(R.string.my_word_file_name));
			Scanner scanner = new Scanner(fis);

			while (scanner.hasNext()) {
				String word = scanner.nextLine();
				if (!isBlank(word)) {
					myWords.add(word.toLowerCase());
				}
			}

			scanner.close();
			fis.close();

		} catch (FileNotFoundException e) {
			Log.d(TAG, "Could not find the file.", e);
		} catch (IOException e) {
			Log.d(TAG, "Could not read from the file.", e);
		}

		return new ArrayList<String>(myWords);
	}

	private void animateFlashCard(boolean back) {
		if ((selectedWords != null) && (!selectedWords.isEmpty())) {

			float fromXValue = 1.0f;
			if (back) {
				fromXValue = -1.0f;
			}

			int currentIndex = 0;
			if (isSightWordSelected()) {
				currentIndex = getSightWordIndex();
			} else {
				currentIndex = getMyWordIndex();
			}

			boolean onEdge = false;
			String edgeMessage = null;
			if (back) {
				if (currentIndex == 0) {
					onEdge = true;
					edgeMessage = "On first word in the list.";
				} else if (currentIndex > 0) {
					currentIndex--;
				}
			} else {
				if (currentIndex == selectedWords.size() - 1) {
					onEdge = true;
					edgeMessage = "On last word in the list.";
				} else if (currentIndex < selectedWords.size() - 1) {
					currentIndex++;
				}
			}

			if (!onEdge) {
				TranslateAnimation sightWordAnimation = new TranslateAnimation(
						Animation.RELATIVE_TO_SELF, fromXValue,
						Animation.RELATIVE_TO_SELF, 0.0f,
						Animation.RELATIVE_TO_SELF, 0.0f,
						Animation.RELATIVE_TO_SELF, 0.0f);

				sightWordAnimation.setDuration(500);
				sightWordAnimation.setFillAfter(true);
				sightWordsTextView.startAnimation(sightWordAnimation);
				sightWordsTextView.setText(selectedWords.get(currentIndex)
						.toLowerCase());

				if (isSightWordSelected()) {
					setSightWordIndex(currentIndex);
				} else {
					setMyWordIndex(currentIndex);
				}
			} else {
				if (!isBlank(edgeMessage)) {
					Toast.makeText(this, edgeMessage, Toast.LENGTH_SHORT)
							.show();
				}
			}
		}

	}

	// Getters and Setters for the preferences

	private int getMyWordIndex() {
		return getPreferences(MODE_PRIVATE).getInt(MY_WORD_INDEX, 0);
	}

	private int getSightWordIndex() {
		return getPreferences(MODE_PRIVATE).getInt(SIGHT_WORD_INDEX, 0);
	}

	private boolean isSightWordSelected() {
		return getPreferences(MODE_PRIVATE).getBoolean(SIGHT_WORD_SELECTED,
				true);
	}

	private void setSightWordSelected(boolean selected) {
		getPreferences(MODE_PRIVATE).edit()
				.putBoolean(SIGHT_WORD_SELECTED, selected).apply();
	}

	private void setSightWordIndex(int index) {
		getPreferences(MODE_PRIVATE).edit().putInt(SIGHT_WORD_INDEX, index)
				.apply();
	}

	private void setMyWordIndex(int index) {
		getPreferences(MODE_PRIVATE).edit().putInt(MY_WORD_INDEX, index)
				.apply();
	}

	private void clearMyWordIndex() {
		setMyWordIndex(0);
	}

	private void clearSightWordIndex() {
		setSightWordIndex(0);
	}

}
